<?php
/**
 * Description of DbDoctrine
 *
 * @author logistic
 */
class Model3_Acl_DbDoctrine extends Model3_Acl
{
    protected $_usersGroupsAdapter;
    protected $_aclPermissionsAdapter;
    protected $_resourcesAdapter;
    protected $_actualResource;

    /*
     * @var $_userGroupsAdapter UsersGroupsTable
     * @var $_aclPermissionsAdapter AclPermissionsTable
     * @var $_resourcesAdapter ResourcesTable
     * @var $_actualResource 
     */
    public function __construct($request = null)
    {
        parent::__construct();
        $this->_aclPermissionsAdapter = MN_AclPermissionsTable::getInstance();
        $this->_resourcesAdapter = MN_ResourcesTable::getInstance();
        $this->_usersGroupsAdapter = MN_UsersGroupsTable::getInstance();
        if($request == null)
        {
            $this->_actualResource = null;
        }
        else
        {
            $nameController = $request->getController();
            $nameAction = $request->getAction();
            $this->setActualResource($nameController, $nameAction);
        }
    }

    public function getUsersGroupsTable()
    {
        return $this->_usersGroupsAdapter;
    }

    public function getAclPermissionsTable()
    {
        return $this->_aclPermissionsAdapter;
    }

    public function getResourcesTable()
    {
        return $this->_resourcesAdapter;
    }

    public function setActualResource($nameController, $nameAction)
    {
        $resourcesAdapter = MN_ResourcesTable::getInstance();
        $result = $resourcesAdapter->existsResource($nameController, $nameAction);
        $this->_actualResource = $result !== false ? $result : null;
        return $this;
    }

    public function getActualResource()
    {
        return $this->_actualResource;
    }

    /**
     * Regresa si el usuario o su grupo tiene permiso de ver el recurso actual
     * @param int $userId
     * @param int $groupId
     * @return boolean
     */
    public function isAllowed($userId, $groupId)
    {
        $finalResult = self::getPermissionMode();        
        if($this->_actualResource == null)
        {
            return false;
        }
        $result = $this->verifyUserToResourcePermission($userId);

        if($result === MN_AclPermissions::ACL_DB_UNDEFINED)
        {
            $group = $this->_usersGroupsAdapter->findOneBy('id', array($groupId));
            while($group !== false && $result === MN_AclPermissions::ACL_DB_UNDEFINED)
            {
                $result = $this->verifyGroupToResourcePermission($group->id);
                
                if($result === MN_AclPermissions::ACL_DB_UNDEFINED)
                {
                    $group = $this->_usersGroupsAdapter->findOneBy('id', array($group->parent_id));
                }
                else
                {
                    $finalResult = $result;
                }
            }
        }
        else
            $finalResult = $result;

        return $finalResult;
    }

    /**
     * Regresa si el usuario recibido tiene o no permiso para el recurso actual
     * @param int $userId
     * @return boolean | int true si tiene permiso, AclPermissions::ACL_DB_UNDEFINED (3) si es falso
     */
    protected function verifyUserToResourcePermission($userId)
    {
        $finalResult = self::getPermissionMode();
        
        $result = $this->_aclPermissionsAdapter->getPermissions($userId, null, $this->_actualResource, MN_AclPermissions::ACL_DB_DENY);
        
        if($result !== false && $result->count() == 0)
        {
            $result = $this->_aclPermissionsAdapter->getPermissions($userId, null, $this->_actualResource, MN_AclPermissions::ACL_DB_ALLOW);
            if($result !== false && $result->count() > 0)
            {
                $finalResult = true;
            }
            else
            {
                $finalResult = MN_AclPermissions::ACL_DB_UNDEFINED;
            }
        }
        return $finalResult;
    }
    /**
     * Regresa si el usuario recibido tiene o no permiso para el recurso actual
     * @param int $groupId
     * @return boolean
     */
    protected function verifyGroupToResourcePermission($groupId)
    {
        $finalResult = false;
        $result = $this->_aclPermissionsAdapter->getPermissions(null, $groupId, $this->_actualResource, MN_AclPermissions::ACL_DB_DENY);

        if($result !== false && $result->count() == 0)
        {
            $result = $this->_aclPermissionsAdapter->getPermissions(null, $groupId, $this->_actualResource, MN_AclPermissions::ACL_DB_ALLOW);
            if($result !== false && $result->count() > 0)
            {
                $finalResult = true;
            }
            else
            {
                $finalResult = MN_AclPermissions::ACL_DB_UNDEFINED;
            }
        }
        return $finalResult;
    }

    public function allowGroups()
    {
        $groups = func_get_args();        
        foreach($groups as $group)
        {
            $res = $this->_aclPermissionsAdapter->existPermission($this->_actualResource, MN_AclPermissions::ACL_DB_ALLOW, $group);
            
            if($res === false)
            {//si no existe el permiso
                $data = array('group_id' => $group, 'resource_id' => $this->_actualResource, 'permission_type' => MN_AclPermissions::ACL_DB_ALLOW);
                $this->_aclPermissionsAdapter->insertPermissions($data);
            }
            else
            {//si existe el permiso
//                $data = array('permission_type'=>AclPermissions::ACL_DB_ALLOW);
//                $this->_aclPermissionsAdapter->updatePermissions($res, $data);
            }            
        }
    }

    public function allowUsers()
    {
        $users = func_get_args();

        foreach($users as $user)
        {
            $res = $this->_aclPermissionsAdapter->existPermission($this->_actualResource, MN_AclPermissions::ACL_DB_ALLOW, false, $user);
            if($res === false)
            {//si no existe el permiso
                $data = array('user_id' => $user, 'resource_id' => $this->_actualResource, 'permission_type' => MN_AclPermissions::ACL_DB_ALLOW);
                $this->_aclPermissionsAdapter->insertPermissions($data);
            }
            else
            {//si existe el permiso
//                $data = array('permission_type'=>AclPermissions::ACL_DB_ALLOW);
//                $this->_aclPermissionsAdapter->updatePermissions($res, $data);
            }
        }
    }

    public function denyGroups()
    {
        $groups = func_get_args();

        foreach($groups as $group)
        {
            if(!($res = $this->_aclPermissionsAdapter->existPermission($this->_actualResource, MN_AclPermissions::ACL_DB_DENY, $group)))
            {//si no existe el permiso
                $data = array('group_id' => $group, 'resource_id' => $this->_actualResource, 'permission_type' => MN_AclPermissions::ACL_DB_DENY);
                $this->_aclPermissionsAdapter->insertPermissions($data);
            }
            else
            {//si existe el permiso
//               $data = array('permission_type'=>AclPermissions::ACL_DB_DENY);
//                $this->_aclPermissionsAdapter->updatePermissions($res, $data);
            }
        }
    }

    public function denyUsers()
    {
        $users = func_get_args();

        foreach($users as $user)
        {
            if(!($res = $this->_aclPermissionsAdapter->existPermission($this->_actualResource, MN_AclPermissions::ACL_DB_DENY, false, $user)))
            {//si no existe el permiso
                $data = array('user_id' => $user, 'resource_id' => $this->_actualResource, 'permission_type' => MN_AclPermissions::ACL_DB_DENY);
                $this->_aclPermissionsAdapter->insertPermissions($data);
            }
            else
            {//si existe el permiso
//                $data = array('permission_type'=>AclPermissions::ACL_DB_DENY);
//                $this->_aclPermissionsAdapter->updatePermissions($res, $data);
            }
        }
    }
}